package com.zuiacsn.java_gobang.game;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zuiacsn.java_gobang.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

@Component
public class Matcher {
    private Queue<User> noramlQueue = new LinkedList<User>();
    private Queue<User> highQueue = new LinkedList<User>();
    private Queue<User> veryHighQueue = new LinkedList<User>();

    @Autowired
    OnlineUserManager onlineUserManager;
    @Autowired
    RoomManager roomManager;
    @Autowired
    ObjectMapper objectMapper;

    public void add(User user) {
        if (user.getScore() < 2000) {
            synchronized (noramlQueue){
                noramlQueue.add(user);
                noramlQueue.notify();
                System.out.println("玩家 " + user.getUsername() + " 进入noramlQueue队列");
            }
        } else if (user.getScore() > 2000 && user.getScore() < 3000) {
            synchronized (highQueue) {
                highQueue.add(user);
                highQueue.notify();
                System.out.println("玩家 " + user.getUsername() + " 进入highQueue队列");
            }
        } else {
            synchronized (veryHighQueue) {
                veryHighQueue.add(user);
                veryHighQueue.notify();
                System.out.println("玩家 " + user.getUsername() + " 进入veryHighQueue队列");
            }
        }
    }

    public void remove(User user) {
        if (user.getScore() < 2000) {
            synchronized (noramlQueue) {
                noramlQueue.remove(user);
                System.out.println("玩家 " + user.getUsername() + " 退出noramlQueue队列");
            }
        } else if (user.getScore() > 2000 && user.getScore() < 3000) {
            synchronized (highQueue) {
                highQueue.remove(user);
                System.out.println("玩家 " + user.getUsername() + " 退出highQueue队列");
            }
        } else {
            synchronized (veryHighQueue) {
                veryHighQueue.remove(user);
                System.out.println("玩家 " + user.getUsername() + " 退出veryHighQueue队列");
            }
        }
    }

    public Matcher() {
        // 在构造方法中创建三个线程去不停地扫描匹配队列
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    handlerMatch(noramlQueue);
                }
            }
        });
        t1.start();

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    handlerMatch(highQueue);
                }
            }
        });
        t2.start();

        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    handlerMatch(veryHighQueue);
                }
            }
        });
        t3.start();
    }

    private void handlerMatch(Queue<User> queue) {
        synchronized (queue) {
            try {
                // 1. 检测玩家个数是否大于2 如果说队列中的玩家人数大于2, 就可以进行匹配操作
                // 使用while循环检查更加合理 因为 如果队列中有一个玩家也是无法完成匹配操作的
                while (queue.size() < 2) {
                    queue.wait();
                }
                // 2.尝试将玩家从队列中取出
                User player1 = queue.poll();
                User player2 = queue.poll();
                System.out.println("匹配出了两个玩家  "+player1.getUsername()+"  "+player2.getUsername());

                // 3. 获取到玩家的socket会话
                WebSocketSession session1 = onlineUserManager.getFromGall(player1.getUserId());
                WebSocketSession session2 = onlineUserManager.getFromGall(player2.getUserId());

                if (session1 == null) {
                    // 玩家1不在线, 无法进行匹配, 将玩家2重新进入匹配队列
                    queue.offer(player2);
                    return;
                }

                if (session2 == null) {
                    // 玩家2不在线, 无法进行匹配, 将玩家1重新进入匹配队列
                    queue.offer(player1);
                    return;
                }

                if (session2 == session1) {
                    // 玩家相同,随机放入一个即可
                    queue.offer(player1);
                    return;
                }

                // 4. 将两个玩家放入一个游戏房间中
                // todo
                Room room = new Room();
                roomManager.add(room, player1.getUserId(), player2.getUserId());
                // 5. 给玩家返回响应信息
                // 通过websocket 构造MatchResponse 给玩家返回 message 为 "matchSuccess"
                MatchResponse matchResponse1 = new MatchResponse();
                matchResponse1.setOk(true);
                matchResponse1.setMessage("matchSuccess");
                session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(matchResponse1)));

                MatchResponse matchResponse2 = new MatchResponse();
                matchResponse2.setOk(true);
                matchResponse2.setMessage("matchSuccess");
                session2.sendMessage(new TextMessage(objectMapper.writeValueAsString(matchResponse2)));
            }catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
}
